<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>深拷贝</title>
</head>

<body>
</body>

</html>
<script>
    // const getType = (data) => {
    //     return Object.prototype.toString.call(data).slice(8, -1).toLowerCase()
    // }
    // 浅拷贝是对基本类型值的拷贝以及对引用数据类型地址的拷贝

    // 应用深拷贝是为了当改变新数据的时候,还需要原来的数据才进行的深拷贝

    const a = 1
    const b = a //一个基本数据的一个复制操作


    // 初始的原数据
    const original = {
        age: 20,
        name: "Zhang",
        address: {
            city: "北京",
            arr1: ["a1", { name: '小红' }]
        },
        arr: ["a", "b", "c"],
        isNull: null,
        isundefined: undefined
    }


    // 可以使用 assign 可以对一个对象进行深拷贝,但是只能拷贝一层数据
    const assignObj = Object.assign({}, original)

    // 也可以使用JSON.stringify 进行深拷贝 (不建议使用)
    const jsonObj = JSON.stringify(original)


    // 引用数据类型进行复制是将这个对象栈中的地址引用了,两个用的是同一个地址
    // 两个对象的地址都指向了同一个数据源,为了保证不会修改数据源,使用递归的方式进行深拷贝
    const newObj = deepClone(original)
    newObj.arr[0] = "sen"
    function deepClone(obj = {}) {
        if (typeof obj !== "object" || obj === null) {
            console.log('基本数据类型', obj);
            return obj
        }
        let result
        // 使用Array.isArray() 进行判断引用数据类型是数组,还是对象
        if (Array.isArray(obj)) {
            result = []
        } else {
            result = {}
        }
        // 使用 for in 循环进行循环数组或对象
        for (let key in obj) {
            // 保证 key 一定是自己的属性,不是原型上的
            if (obj.hasOwnProperty(key)) {
                // 进行递归调用一次将每一个值进行判断赋值
                result[key] = deepClone(obj[key])
            }
        }
        // 处理好的结果进行返回
        return result
    }
    console.log(original); //原数据
    console.log(newObj); //深复制的数据
</script>